﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SQLite;
using System.Data;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;

namespace MwanaDOC
{
    public class Documento
    {
        //Atributos do documento
        private int idDocumento;
        private string titulo;
        private string descricao;
        private string palavra_chave;
        private string doc_path;
        private int materia_idMateria;
        private string docExtension = ".txt";
        LogToFile lg = new LogToFile();
        public string novoDoc;
        
        
        Global gb = new Global();
        string appDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

            

        #region Propriedades
        public int IdDocumento
        {
            get { return this.idDocumento; }
            set { this.idDocumento = value; }
        }

        public string Titulo
        {
            get { return this.titulo; }
            set { this.titulo = value; }
        }

        public string Descricao
        {
            get { return this.descricao; }
            set { this.descricao = value; }
        }
        public string Palavra_Chave
        {
            get { return this.palavra_chave; }
            set { this.palavra_chave = value; }
        }
        public string Doc_Path
        {
            get { return this.doc_path; }
            set { this.doc_path = value; }
        }
        public int Materia_idMateria
        {
            get { return this.materia_idMateria; }
            set { this.materia_idMateria = value; }
        }
        public string DocExtension
        {
            get { return this.docExtension; }
            set { this.docExtension = value; }
        }
        #endregion

        /// <summary>
        /// Retorna a lista de disciplinas(matérias)
        /// </summary>
        /// <returns>leitor-SQLiteDataReades</returns>
        public SQLiteDataReader getMateria()
        {
            string query = "SELECT idMateria, Nome FROM materia";
            SQLiteDataReader leitor = null;

            try
            {
                leitor = gb.executeReader(query);
            }
            catch (Exception e)
            {
                MessageBox.Show("Não foi possível retornar a lista de disciplinas","Erro");
                lg.log(this.GetType().Name, "getMateria", e.Message, e.StackTrace);
            }

            return leitor;

        }

        /// <summary>
        /// Pega a sigla da matéria(disciplina) selecionada
        /// </summary>
        /// <param name="materia">O Nome da matéria ou disciplina</param>
        /// <returns>Sigla</returns>
        public string pegaSigla(string materia)
        {
            string sql = "SELECT Sigla FROM Materia WHERE Nome='"+materia+"'";
            string sigla = null;

            try
            {
                sigla = gb.executaComResultado(sql).ToString();
            }
            catch (Exception e)
            {
                MessageBox.Show("Erro ao retornar a sigla da matéria","Erro");
                lg.log(this.GetType().Name, "pegaSigla", e.Message, e.StackTrace);
            }
                return sigla;
          
           
            
            
        }

        /// <summary>
        /// Método para gravar o arquivo no diretório de dados da aplicação
        /// </summary>
        /// <param name="materia">Sigla da matéria(disciplina)</param>
        /// <param name="docPath">O endereço inicial( de origem) do arquivo</param>
        /// <param name="docTitle">O Título do documento( que será o novo nome do domento)</param>
        public bool uploadDoc(String materia, string docPath, string docTitle,bool mover)
        { 
            String baseDir;
            bool passed = false;

            //Diretório de dados da aplicação.
           
            baseDir = Global.baseDir + materia;

            

            try
            {
                /*
                 * Criar novo título do documento.
                 * pegar a extensão do documento
                 * */
                FileInfo info = new FileInfo(docPath);
                string nome = docTitle;
                string extensão = info.Extension;
                docExtension = extensão;
                string endCompleto = baseDir+ "\\" + nome+extensão;
                novoDoc = endCompleto;

                DialogResult result;

            
                if (File.Exists(endCompleto))
                {
                    result = MessageBox.Show("Arquivo já existe.Deseja substituí-lo?", "Arquivo existente!", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);

                    if (result == DialogResult.OK)
                    {
                        if (mover == true)
                            File.Move(docPath, endCompleto);
                        else
                            File.Copy(docPath, endCompleto, true);

                        passed = true;
                    }
                    else
                        passed = false;
                }
                else
                {
                    if (mover == true)
                        File.Move(docPath, endCompleto);
                    else
                        File.Copy(docPath, endCompleto);

                    passed = true;
                }
            }
            catch (DirectoryNotFoundException d)
            {
                passed = false;
                MessageBox.Show("Diretório não encontrado", "operação não realizada");
                lg.log(this.GetType().Name, "uploadDoc", d.Message, d.StackTrace);
            }
            catch (UnauthorizedAccessException u)
            {
                passed = false;
                MessageBox.Show("Acesso negado", "operação não realizada");
                lg.log(this.GetType().Name, "uploadDoc", u.Message, u.StackTrace);
            }
            catch (FileNotFoundException f)
            {
                passed = false;
                MessageBox.Show("Arquivo não encontrado", "operação não realizada");
                lg.log(this.GetType().Name, "uploadDoc", f.Message, f.StackTrace);
                
            }
            catch (PathTooLongException pLong)
            {
                passed = false;
                MessageBox.Show("O caminho especificado para o arquivo é muito longo\nTente outro", "operação não realizada");
                lg.log(this.GetType().Name, "uploadDoc", pLong.Message, pLong.StackTrace);
            }
            catch (TimeoutException t)
            {
                passed = false;
                MessageBox.Show("Erro.Tempo esgotado",  "operação não realizada");
                lg.log(this.GetType().Name, "uploadDoc", t.Message, t.StackTrace);
            }

            catch (Exception err)
            {
                passed = false;
                //throw new Exception ("Erro inesperado!\nOperação não pode ser completada");
                lg.log(this.GetType().Name, "uploadDoc", err.Message, err.StackTrace);
            }

            return passed;

        }

        public bool Save(string materia)
        {
            string buscaCodMateriaSQL = "select idMateria From Materia Where Nome='"+materia+"'"; 
            //this.Doc_Path = novoDoc;
            bool result = false;
            string sigla = pegaSigla(materia);

            if (sigla == null)
            {
                result = false;
                return result;
            }
            try
            {
                this.Materia_idMateria = Convert.ToInt32(gb.executaComResultado(buscaCodMateriaSQL));
                if (uploadDoc(sigla, this.doc_path, this.titulo,false))
                {

                    //get the current doc path
                    this.Doc_Path = novoDoc;

                    string sql = string.Format("INSERT INTO Documentos ( Titulo, Descricao, Palavra_Chave, DocPath,Materia_idMateria,Extensao)" +
                                            " VALUES ('{0}','{1}', '{2}', '{3}', '{4}', '{5}' )", titulo, descricao, palavra_chave, doc_path, materia_idMateria, docExtension);

                    gb.executa(sql);

                    result = true;
                }
                else
                {
                    result = false;
                }
            }
            catch (SQLiteException e)
            {
                /* Se for lançada apenas uma excepção do Sqllite provavelmente o documento foi copiado
                * para o novo endereço.Por isso, será necessário apagá-lo
                 */
                result = false;
                lg.log(this.GetType().Name, "Documento.Save", e.Message, e.StackTrace);
                deleteDoc(sigla, this.doc_path, this.titulo);

                
            }
            catch (UnauthorizedAccessException erroNegado)
            {
                result = false;
                MessageBox.Show("Acesso negado","Erro");
                lg.log(this.GetType().Name, "Documento.Save", erroNegado.Message, erroNegado.StackTrace);
            }
            catch (DirectoryNotFoundException f)
            {
                result = false;
                MessageBox.Show("Diretório não encontrado.Não foi possível salvar o arquivo");
                lg.log(this.GetType().Name, "Documento.Save", f.Message, f.StackTrace);
            }

            return result;
        }

        public void deleteDoc(String materia, string docPath, string docTitle)
        {
            String baseDir;

            //Diretório de dados da aplicação.
            baseDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            baseDir = baseDir + "\\MwanaDOC\\Disciplinas\\" + materia;

            ///*
            // * pegar a extensão do documento
            // * */
            //FileInfo info = new FileInfo(docPath);
            //string nome = docTitle;
            //string extensão = info.Extension;
            //Criar o endereço completo do documento
            string endCompleto = baseDir + "\\" + docTitle;

            try
            {
                if (File.Exists(endCompleto))
                {
                    File.Delete(endCompleto);
                }
            }
            catch (Exception e)
            {
                lg.log(this.GetType().Name, "Documento.deleteDoc", e.Message, e.StackTrace);
                
            }
        }

        public BindingSource getByContent(string content)
        {
            StringBuilder query = new StringBuilder();

            DataSet ds = new DataSet();
            BindingSource bsDoc = new BindingSource();
            string endereco;
            string conteudo;

            try
            {

                SQLiteDataReader listaDocumentos = gb.executeReader("select DocPath From Documentos");
                string sql = "select d.idDocumentos as Código, d.Titulo as Título, (select m.Nome from Materia m Where m.idMateria=d.Materia_idMateria) as Matéria From Documentos d ";
                query.Append(sql);

                int i = 0;

                if (listaDocumentos.HasRows)
                {

                    while (listaDocumentos.Read())
                    {
                        endereco = listaDocumentos.GetString(0);
                        try
                        {
                            //conteudo = File.ReadAllText(endereco);
                            using (StreamReader sr = new StreamReader(endereco))
                            {
                                conteudo = sr.ReadToEnd();
                            }

                                
                            if (conteudo.Contains(content))
                            {
                                //bsDoc = gb.getByContent(sql+endereco+"'");
                                //Form1.bsGeral.Add(bsDoc);


                                if (i == 0)
                                {
                                    query.Append(" Where DocPath='" + endereco + "' ");
                                    i++;
                                }
                                else
                                {
                                    query.Append(" OR DocPath='" + endereco + "' ");
                                    i++;
                                }

                            }
                        }
                        catch (IOException)
                        {

                            continue;
                        }

                    }

                    if (query.ToString().Contains("DocPath"))
                    {

                        bsDoc = gb.getByContent(query.ToString());
                    }
                }
            }
            catch (Exception e)
            {

                MessageBox.Show("Erro ao ler conteúdo do arquivo", "Erro ao ler conteúdo do arquivo");
                lg.log(this.GetType().Name, "getByContent", e.Message,e.StackTrace);
            }


            return bsDoc;
        }

        /// <summary>
        /// Retorna o endereço do documento no disco a apartir do seu título
        /// </summary>
        /// <param name="docName">O título do documento</param>
        /// <returns >documento</returns>
        public string getDocPath(string docName)
        {
            string docPath = null;

            string sql = "select DocPath from documentos where Titulo='" + docName + "'";
            try
            {
                docPath = gb.executaComResultado(sql).ToString();
            }
            catch (Exception e)
            {
                lg.log(this.GetType().Name, "getDocPath", e.Message, e.StackTrace);
            }

            return docPath;
        }


        /// <summary>
        /// Retorna o documento buscando pelo código da matéria
        /// </summary>
        /// <param name="id">ID da matéria</param>
        /// <returns></returns>
        internal BindingSource getByIdMateria(int id)
        {
            string sql = "select d.idDocumentos as Código, d.Titulo as Título, (select m.Nome from Materia m Where m.idMateria=d.Materia_idMateria) as Matéria From Documentos d Where d.Materia_idMateria ="+id;
            BindingSource bs = new BindingSource();

            try
            {
                bs = gb.getByContent(sql);
            }
            catch (Exception e)
            {
                lg.log(this.GetType().Name, "getByIdMateria", e.Message, e.StackTrace);
            }

            return bs;
        }

        /// <summary>
        /// Para busca detalhada(avançada)
        /// </summary>
        /// <param name="opcaoBusca">Opção de busca. Enum do tipo Global.opcaoBusca</param>
        /// <param name="p">O texto para busca</param>
        /// <returns>BindingSource</returns>
        internal BindingSource getDetalhada(Global.opcaoBusca opcaoBusca, string p)
        {
            string sql = "select d.idDocumentos as Código, d.Titulo as Título, (select m.Nome from Materia m Where m.idMateria=d.Materia_idMateria) as Matéria From Documentos d inner join Materia ma on d.Materia_idMateria=ma.idMateria Where ";
            BindingSource bs = new BindingSource();

            if (opcaoBusca == Global.opcaoBusca.Titulo)
            {
                sql = sql + "d.Titulo LIKE '%" + p + "%'";
            } else
            if (opcaoBusca == Global.opcaoBusca.Professor)
            {
                sql = sql + "ma.Prof_Titular LIKE '%" + p + "%'";
            } else
            if (opcaoBusca == Global.opcaoBusca.Palavra)
            {
                sql = sql + "d.Palavra_Chave LIKE '%" + p + "%'";
            } else
            if (opcaoBusca == Global.opcaoBusca.Periodo)
            {
                sql = sql + "ma.Periodo =" + p + " ";
            }

            try
            {
                bs = gb.getByContent(sql);
            }
            catch (Exception e)
            {
                lg.log(this.GetType().Name, "getDetalhada", e.Message, e.StackTrace);
            }
            
            return bs;
        }

        /// <summary>
        /// Apaga o registro do documento no banco de dados
        /// </summary>
        /// <param name="cod"></param>
        public bool ApagarDoc(int cod)
        {
            bool passed = false;
            string sql = "DELETE FROM Documentos Where idDocumentos=" + cod;
            string sqlCaminho = "SELECT DocPath FROM Documentos Where idDocumentos=" + cod;
            string caminho;

            
            caminho = gb.executaComResultado(sqlCaminho).ToString();
            try
            {
                gb.executa(sql);
                passed = true;
            }
            catch(Exception e )
            {
                passed = false;
                lg.log(this.GetType().Name, "ApagarDoc", e.Message, e.StackTrace);
            }


           

            //Mandar o arquivo físico pra lixeira
            if (!apagarArquivo(caminho))
                passed = false;

            return passed;
        }

        /// <summary>
        /// Apaga o arquivo do disco.
        /// Uma cópia do arquivo é salvo na lixeira da aplicação
        /// </summary>
        /// <param name="caminho">Caminho(Path)</param>
        /// <returns>true or false</returns>
        public bool apagarArquivo(string caminho)
        {
            String endCompleto = caminho;
            bool passed = false;

            //criando novo nome para o arquivo na lixeira
            string novoNome;
            FileInfo info = new FileInfo(endCompleto);
            string data = DateTime.Now.Day.ToString() + "_" + DateTime.Now.Month.ToString() +"_"+ 
                           DateTime.Now.Year.ToString() +"_"+ DateTime.Now.Hour.ToString() +"_"+DateTime.Now.Minute.ToString();
            
            novoNome = info.Name +data+ info.Extension;
            

            try
            {
             
                if (File.Exists(endCompleto))
                {
                    //File.Delete(endCompleto);
                    File.Move(endCompleto, Global.lixeira+"\\"+novoNome);
                    passed = true;
                }
                //else
                //{
                //    MessageBox.Show("Arquivo não existe");
                //}
            }
            catch (DirectoryNotFoundException e)
            {
                passed = false;
                MessageBox.Show("Diretório não encontrado", "operação não realizada");
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
            }
            catch (UnauthorizedAccessException e)
            {
                passed = false;
                MessageBox.Show("Acesso negado", "operação não realizada");
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
            }
            catch (FileNotFoundException e)
            {
                passed = false;
                MessageBox.Show("Arquivo não encontrado", "operação não realizada");
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
            }
            catch (PathTooLongException e)
            {
                passed = false;
                MessageBox.Show("O caminho especificado para o arquivo é muito longo\nTente outro", "operação não realizada");
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
            }
            catch (TimeoutException e)
            {
                passed = false;
                MessageBox.Show("Erro.Tempo esgotado", "operação não realizada");
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
            }

            catch (Exception e)
            {
                passed = false;
                lg.log(this.GetType().Name, "apagarArquivo", e.Message, e.StackTrace);
                //throw new Exception ("Erro inesperado!\nOperação não pode ser completada");
            }

            return passed;
        }

        internal bool Update(string nomeMateria)
        {
            string buscaCodMateriaSQL = "select idMateria From Materia Where Nome='" + nomeMateria + "'";
            //this.Doc_Path = novoDoc;
            string sigla = pegaSigla(nomeMateria);
            bool result = false;
            try
            {
                this.Materia_idMateria = Convert.ToInt32(gb.executaComResultado(buscaCodMateriaSQL));
                
                if (uploadDoc(sigla, this.doc_path, this.titulo,true))
                {

                    //get the current doc path
                    this.Doc_Path = novoDoc;

                    string sql = string.Format("UPDATE Documentos SET Titulo='{0}', Descricao='{1}', Palavra_Chave='{2}', DocPath='{3}',Materia_idMateria='{4}',Extensao='{5}' " +
                                            " WHERE idDocumentos={6}", titulo, descricao, palavra_chave, doc_path, materia_idMateria, docExtension, idDocumento);

                    gb.executa(sql);

                    result = true;
                }
                else
                {
                    result = false;
                }
            }
            catch (SQLiteException e)
            {
                /* Se for lançada apenas uma excepção do Sqllite provavelmente o documento foi copiado
                * para o novo endereço.Por isso, será necessário apagá-lo
                 */
                result = false;
                deleteDoc(sigla, this.doc_path, this.titulo);
                lg.log(this.GetType().Name, "Documento.Update", e.Message, e.StackTrace);
                
            }
            catch (UnauthorizedAccessException erroNegado)
            {
                result = false;
                MessageBox.Show("Acesso negado \nDetalhes do erro: " + erroNegado.Message);
                lg.log(this.GetType().Name, "Documento.Update", erroNegado.Message, erroNegado.StackTrace);
            }
            catch (DirectoryNotFoundException e)
            {
                result = false;
                MessageBox.Show("Diretório não encontrado.Não foi possível salvar o arquivo");
                lg.log(this.GetType().Name, "Documento.Update", e.Message, e.StackTrace);
            }

            return result;
        }

        //internal void Update(string nomeMateria, Documento doc)
        //{
        //    throw new NotImplementedException();
        //}

        internal BindingSource getByNomeMateria(string nome)
        {
            string sql = "select d.idDocumentos as Código, d.Titulo as Título, (select m.Nome from Materia m Where m.idMateria=d.Materia_idMateria) as Matéria From Documentos d inner join Materia ma on ma.idMateria=d.Materia_idMateria Where ma.Nome ='" + nome+ "'";
            BindingSource bs = new BindingSource();

            try
            {
                bs = gb.getByContent(sql);
            }
            catch (Exception e)
            {
                lg.log(this.GetType().Name, "getByIdMateria", e.Message, e.StackTrace);
            }

            return bs;
        }
    }
}
